#pragma once

#include <iostream>
#include <memory>
#include "Common.hpp"
#include "Socket.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"
#include "Connection.hpp"
#include "Reactor.hpp"
#include "IOServer.hpp"
#include "Protocol.hpp"
#include "Calculator.hpp"

using namespace LogModule;
using namespace SocketModule;

class Listener : public Connection
{
public:
    Listener(int port)
        : _listensock(std::make_unique<TcpSocket>())
        , _port(port)
    {
        _listensock->BulidTcpSocket(_port);
        SetSockfd(_listensock->Fd());
        SetEvents(EPOLLIN | EPOLLET);
    }

    virtual void Recver() override
    {
        // 读事件就绪，而且是listensockfd就绪
        // IO处理 ----- 获取新连接
        // 你如何知道，一次来的只有一个连接，你怎么保证你一次读完了么？
        while(true)
        {
            InetAddr peer;
            int aerrno = 0;
            int sockfd = _listensock->Acceptor(&peer, &aerrno);
            if(sockfd > 0)
            {
                // success
                // 不能直接读取，添加到epoll
                LOG(LogLevel::DEBUG) << "Accept success, " << sockfd;
                // 普通的文件描述符非阻塞
                SetNonBlock(sockfd);
                // 2.sockfd包装成Connection
                auto conn = std::make_shared<IOService>(sockfd);
                conn->REgisterOnMessage(HandleRequest);
                // 3.插入到EpollServer
                GetOwner()->InsertConnection(conn);
            }
            else
            {
                if(aerrno == EAGAIN || aerrno == EWOULDBLOCK)
                {
                    LOG(LogLevel::DEBUG) << "accepter all connection ... done";
                    break;
                }
                else if(aerrno == EINTR)
                {
                    LOG(LogLevel::DEBUG) << "accepter interrupted by signal, continue";
                    continue;
                }
                else
                {
                    LOG(LogLevel::WARNING) << "accepter error ... Ignore";
                    break;
                }
            }
        }
        LOG(LogLevel::INFO) << "Accepter start";
    }

    virtual void Sender() override
    {}

    virtual void Exceptor() override
    {}

    int Sockfd() const { return _listensock->Fd(); }

    ~Listener() 
    {
        _listensock->Close();
    }
private:
    int _port;
    std::unique_ptr<Socket> _listensock;
};